package org.example.rzfx.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.example.rzfx.entity.Alarm;
import org.example.rzfx.entity.Log;
import org.example.rzfx.entity.LogSource;
import org.example.rzfx.mapper.AlarmMapper;
import org.example.rzfx.mapper.LogMapper;
import org.example.rzfx.mapper.LogSourceMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Dashboard服务
 * 提供仪表盘数据，使用Redis缓存提升性能
 */
@Service
public class DashboardService {
    
    @Resource
    private LogMapper logMapper;
    
    @Resource
    private AlarmMapper alarmMapper;
    
    @Resource
    private LogSourceMapper logSourceMapper;
    
    @Resource
    private RedisService redisService;
    
    /**
     * 获取Dashboard概览数据（带缓存，5分钟更新）
     */
    public Map<String, Object> getDashboardOverview() {
        String cacheKey = RedisService.dashboardCacheKey();
        
        // 尝试从缓存获取
        Object cached = redisService.get(cacheKey);
        if (cached != null) {
            return (Map<String, Object>) cached;
        }
        
        // 构建Dashboard数据
        Map<String, Object> overview = new HashMap<>();
        
        // 今日日志统计
        LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
        LocalDateTime now = LocalDateTime.now();
        
        LambdaQueryWrapper<Log> todayWrapper = new LambdaQueryWrapper<>();
        todayWrapper.ge(Log::getTimestamp, todayStart).le(Log::getTimestamp, now);
        long todayLogCount = logMapper.selectCount(todayWrapper);
        overview.put("todayLogCount", todayLogCount);
        
        // 今日错误日志统计
        LambdaQueryWrapper<Log> errorWrapper = new LambdaQueryWrapper<>();
        errorWrapper.ge(Log::getTimestamp, todayStart)
                   .le(Log::getTimestamp, now)
                   .in(Log::getLogLevel, Arrays.asList("ERROR", "FATAL"));
        long todayErrorCount = logMapper.selectCount(errorWrapper);
        overview.put("todayErrorCount", todayErrorCount);
        
        // 未处理告警统计
        LambdaQueryWrapper<Alarm> alarmWrapper = new LambdaQueryWrapper<>();
        alarmWrapper.eq(Alarm::getStatus, 0);
        long unhandledAlarmCount = alarmMapper.selectCount(alarmWrapper);
        overview.put("unhandledAlarmCount", unhandledAlarmCount);
        
        // 采集源统计
        long totalSourceCount = logSourceMapper.selectCount(null);
        LambdaQueryWrapper<LogSource> activeWrapper = new LambdaQueryWrapper<>();
        activeWrapper.eq(LogSource::getStatus, 1);
        long activeSourceCount = logSourceMapper.selectCount(activeWrapper);
        overview.put("totalSourceCount", totalSourceCount);
        overview.put("activeSourceCount", activeSourceCount);
        
        // 最近24小时日志趋势
        List<Map<String, Object>> last24HoursTrend = getLast24HoursTrend();
        overview.put("last24HoursLogTrend", last24HoursTrend);
        
        // 日志级别分布
        Map<String, Long> levelDistribution = getLogLevelDistribution();
        overview.put("levelDistribution", levelDistribution);
        
        // 系统分布
        Map<String, Long> systemDistribution = getSystemDistribution();
        overview.put("systemDistribution", systemDistribution);
        
        // 缓存5分钟
        redisService.set(cacheKey, overview, 5, TimeUnit.MINUTES);
        
        return overview;
    }
    
    /**
     * 获取最近24小时日志趋势（每小时统计）
     */
    private List<Map<String, Object>> getLast24HoursTrend() {
        List<Map<String, Object>> trend = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:00");
        
        for (int i = 23; i >= 0; i--) {
            LocalDateTime hourStart = LocalDateTime.now().minusHours(i).withMinute(0).withSecond(0);
            LocalDateTime hourEnd = hourStart.plusHours(1);
            
            LambdaQueryWrapper<Log> wrapper = new LambdaQueryWrapper<>();
            wrapper.ge(Log::getTimestamp, hourStart).lt(Log::getTimestamp, hourEnd);
            long count = logMapper.selectCount(wrapper);
            
            Map<String, Object> point = new HashMap<>();
            point.put("time", hourStart.format(formatter));
            point.put("count", count);
            trend.add(point);
        }
        
        return trend;
    }
    
    /**
     * 获取日志级别分布（今日）
     */
    private Map<String, Long> getLogLevelDistribution() {
        String cacheKey = RedisService.statsCacheKey("level_distribution");
        
        // 尝试从缓存获取
        Object cached = redisService.get(cacheKey);
        if (cached != null) {
            return (Map<String, Long>) cached;
        }
        
        LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
        LambdaQueryWrapper<Log> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(Log::getTimestamp, todayStart);
        List<Log> logs = logMapper.selectList(wrapper);
        
        Map<String, Long> distribution = logs.stream()
            .collect(Collectors.groupingBy(Log::getLogLevel, Collectors.counting()));
        
        // 缓存10分钟
        redisService.set(cacheKey, distribution, 10, TimeUnit.MINUTES);
        
        return distribution;
    }
    
    /**
     * 获取系统分布（今日）
     */
    private Map<String, Long> getSystemDistribution() {
        String cacheKey = RedisService.statsCacheKey("system_distribution");
        
        // 尝试从缓存获取
        Object cached = redisService.get(cacheKey);
        if (cached != null) {
            return (Map<String, Long>) cached;
        }
        
        LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
        LambdaQueryWrapper<Log> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(Log::getTimestamp, todayStart);
        List<Log> logs = logMapper.selectList(wrapper);
        
        Map<String, Long> distribution = logs.stream()
            .collect(Collectors.groupingBy(Log::getSystemType, Collectors.counting()));
        
        // 缓存10分钟
        redisService.set(cacheKey, distribution, 10, TimeUnit.MINUTES);
        
        return distribution;
    }
    
    /**
     * 获取统计数据（缓存）
     */
    public Map<String, Object> getStatistics(String timeDimension) {
        String cacheKey = "stats:dimension:" + timeDimension;
        
        // 尝试从缓存获取
        Object cached = redisService.get(cacheKey);
        if (cached != null) {
            return (Map<String, Object>) cached;
        }
        
        Map<String, Object> stats = new HashMap<>();
        LocalDateTime startTime;
        
        // 根据时间维度确定开始时间
        switch (timeDimension) {
            case "1d":
                startTime = LocalDateTime.now().minusDays(1);
                break;
            case "7d":
                startTime = LocalDateTime.now().minusDays(7);
                break;
            case "30d":
                startTime = LocalDateTime.now().minusDays(30);
                break;
            default:
                startTime = LocalDateTime.now().minusDays(7);
        }
        
        // 统计日志总数
        LambdaQueryWrapper<Log> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(Log::getTimestamp, startTime);
        long totalCount = logMapper.selectCount(wrapper);
        stats.put("totalCount", totalCount);
        
        // 统计错误日志
        LambdaQueryWrapper<Log> errorWrapper = new LambdaQueryWrapper<>();
        errorWrapper.ge(Log::getTimestamp, startTime)
                   .in(Log::getLogLevel, Arrays.asList("ERROR", "FATAL"));
        long errorCount = logMapper.selectCount(errorWrapper);
        stats.put("errorCount", errorCount);
        
        // 缓存15分钟
        redisService.set(cacheKey, stats, 15, TimeUnit.MINUTES);
        
        return stats;
    }
    
    /**
     * 清除Dashboard缓存
     */
    public void clearDashboardCache() {
        redisService.delete(RedisService.dashboardCacheKey());
        redisService.delete(RedisService.statsCacheKey("level_distribution"));
        redisService.delete(RedisService.statsCacheKey("system_distribution"));
    }
}

